package com.xiangban.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.binarywang.wxpay.bean.entpay.EntPayRequest;
import com.github.binarywang.wxpay.bean.entpay.EntPayResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.xiangban.config.WxConfig;
import com.xiangban.exception.BizException;
import com.xiangban.model.TSystem;
import com.xiangban.model.TSystemConfig;
import com.xiangban.model.res.ApiResult;
import com.xiangban.model.res.ApiResultCode;
import com.xiangban.service.fegin.SystemServiceFeign;
import com.xiangban.utils.HttpClientUtil;
import com.xiangban.utils.WXConfigUtil;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Service;

import javax.xml.ws.Action;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import static com.xiangban.utils.CommonUtil.BizEmpty;
import static com.xiangban.utils.CommonUtil.getHostIp;

@Service
@Slf4j
public class PayServiceImpl {
    @Autowired
    private SystemServiceFeign systemServiceFeign;
    @Autowired
    private WxConfig wxConfig;


    public String payBack(String resXml) {//回调通知
        System.out.println("resXml******:" + resXml);
        WXConfigUtil config = null;
        try {
            config = new WXConfigUtil();
        } catch (Exception e) {
            e.printStackTrace();
        }
        WXPay wxpay = new WXPay(config);
        String xmlBack = "";
        Map<String, String> notifyMap = null;
        try {
            notifyMap = WXPayUtil.xmlToMap(resXml);         // 调用官方SDK转换成map类型数据
            if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {//验证签名是否有效，有效则进一步处理
                String return_code = notifyMap.get("return_code");//状态
                System.out.println("return_code******" + return_code);
                String out_trade_no = notifyMap.get("out_trade_no");//商户订单号
                if (return_code.equals("SUCCESS")) {
                    if (out_trade_no != null) {
                        // 注意特殊情况：订单已经退款，但收到了支付结果成功的通知，不应把商户的订单状态从退款改成支付成功
                        // 注意特殊情况：微信服务端同样的通知可能会多次发送给商户系统，所以数据持久化之前需要检查是否已经处理过了，处理了直接返回成功标志

                        xmlBack = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
                    } else {
                        //log.info("微信手机支付回调失败订单号:{}", out_trade_no);
                        xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                    }
                }
                return xmlBack;
            } else {
                // 签名错误，如果数据里没有sign字段，也认为是签名错误
                //失败的数据要不要存储？
                //log.error("手机支付回调通知签名错误");
                xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                return xmlBack;
            }
        } catch (Exception e) {
            //log.error("手机支付回调通知失败", e);
            xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
        }
        return xmlBack;
    }

    public Object unifiedOrder(HashMap<String, String> map) throws Exception {
        String accessId = map.get("accessId");//系统帐户
        String payType = map.get("payType");//支付类型 ：JSAPI APP
        String price = map.get("price");//金额 单位分
        String openId = map.get("openId"); //小程序支付携带openId
        String attach = map.get("attach") == null ? "" : map.get("attach");//自定义参数

        String wasteNumber = map.get("wasteNumber"); //流水号
        if (BizEmpty(accessId)) {
            throw new BizException(ApiResultCode.ACCESS_ID_NULL);
        }
        if (BizEmpty(payType)) {
            throw new BizException(ApiResultCode.PAY_TYPE_NULL);
        }
        if (BizEmpty(price)) {
            throw new BizException(ApiResultCode.PRICE_NULL);
        }
        if (BizEmpty(wasteNumber)) {
            throw new BizException(ApiResultCode.WATER_NUMBER_NULL);
        }


        //获取system配置
        TSystem tSystem = new TSystem();
        tSystem.setAccessId(accessId);
        //或取system
        ApiResult<TSystem> system = systemServiceFeign.selectSystemByAccessId(tSystem);
        //获取系统配置信息
        ApiResult<TSystemConfig> systemConfig = systemServiceFeign.getSystemConfigByAccessId(tSystem);
        //

        if (!system.isSuccess() || !systemConfig.isSuccess()) {
            throw new BizException(ApiResultCode.SYS_ERROR);
        }
        HashMap<String, String> doUnifiedOrderParameter = new HashMap<>();
        doUnifiedOrderParameter.put("WX_MACH_ID", system.getDataMap().getWxMchId());//商户号
        doUnifiedOrderParameter.put("WX_PAY_NOTIFY", systemConfig.getDataMap().getWxPayNotify());//回调通知地址
        doUnifiedOrderParameter.put("price", price);
        doUnifiedOrderParameter.put("payType", payType);
        doUnifiedOrderParameter.put("wasteNumber", wasteNumber);
        doUnifiedOrderParameter.put("attach", attach == null ? "" : attach);//自定义参数
        if ("JSAPI".equals(payType)) {
            doUnifiedOrderParameter.put("APP_ID", system.getDataMap().getWxAppletsId());//系统帐户
            doUnifiedOrderParameter.put("APP_KEY", system.getDataMap().getWxMchSecret()); //商户密钥
            doUnifiedOrderParameter.put("OPEN_ID", openId); //openId
        } else if ("APP".equals(payType)) {
            doUnifiedOrderParameter.put("APP_ID", system.getDataMap().getWxAppId()); //小程序id
            doUnifiedOrderParameter.put("APP_KEY", system.getDataMap().getWxAppSecret()); //小程序密钥
        }

        return doUnifiedOrder(doUnifiedOrderParameter);

    }

    public Map<String, String> doUnifiedOrder(HashMap<String, String> map) {
        // 发起微信支付
        log.info("=========发起支付===========");
        log.info("=========支付参数==========="+map);
        WXPay wxpay = null;
        Map<String, String> result = new HashMap<>();
        Map<String, String> data = new HashMap<>();
        //处理订单金额
        try {
            log.info("++++++ttr");
            WXConfigUtil config = new WXConfigUtil();
            log.info("++++++ttH");


            config.setAPP_ID(map.get("APP_ID"));//appid
            config.setAPP_KEY(map.get("APP_KEY"));//小程序/app密钥
            config.setMCH_ID(map.get("WX_MACH_ID"));//商户号
            wxpay = new WXPay(config);
            log.info("000000");

            data.put("appid", map.get("APP_ID"));  //appid
            data.put("mch_id", map.get("WX_MACH_ID"));//商户号
            data.put("nonce_str", WXPayUtil.generateNonceStr()); //随机字符串
            data.put("body", "积分充值");//描述
            data.put("out_trade_no", map.get("wasteNumber")); // 订单唯一编号, 不允许重复
            data.put("total_fee", map.get("price")); // 订单金额, 单位分
            data.put("spbill_create_ip", getHostIp()); // 下单ip
            data.put("notify_url", map.get("WX_PAY_NOTIFY")); // 订单结果通知, 微信主动回调此接口
            data.put("trade_type", map.get("payType")); // 支付类型
            data.put("openid", map.get("OPEN_ID"));
            data.put("attach", map.get("attach") == null ? "" : map.get("attach"));//自定义参数

            log.info("================发起支付参数：" + JSON.toJSONString(data));
            String sign = WXPayUtil.generateSignature(data, map.get("APP_KEY"));
            data.put("sign", sign);
            Map<String, String> response = wxpay.unifiedOrder(data);
            log.info("++++++"+response);
            String returnCode = response.get("return_code");
            System.out.println("returnCode:" + returnCode);
            if (!"SUCCESS".equals(returnCode)) {
                return null;
            }
            String resultCode = response.get("result_code");
            System.out.println("resultCode:" + resultCode);
            if (!"SUCCESS".equals(resultCode)) {
                return null;
            }
            String prepay_id = response.get("prepay_id");
            System.out.println("prepay_id:" + prepay_id);
            if (prepay_id == null) {
                return null;
            }
            //  前端调起微信支付必要参数
            if ("JSAPI".equals(map.get("payType"))) {
                String packages = "prepay_id=" + prepay_id;
                Map<String, String> wxPayMap = new HashMap<String, String>();
                wxPayMap.put("appId", config.getAppID());//appid
                wxPayMap.put("timeStamp", System.currentTimeMillis() / 1000 + "");//时间戳秒
                wxPayMap.put("nonceStr", WXPayUtil.generateNonceStr());//随机串
                wxPayMap.put("package", packages);//数据包
                wxPayMap.put("signType", "MD5");//签名方式
                String packageSign = WXPayUtil.generateSignature(wxPayMap, map.get("APP_KEY"), WXPayConstants.SignType.MD5);
                wxPayMap.put("paySign", packageSign);
                result.putAll(wxPayMap);
            } else if ("APP".equals(map.get("payType"))) {
                Map<String, String> wxPayMap = new HashMap<String, String>();
                wxPayMap.put("appid", config.getAppID());
                wxPayMap.put("timestamp", System.currentTimeMillis() / 1000 + "");
                wxPayMap.put("noncestr", WXPayUtil.generateNonceStr());
                wxPayMap.put("prepayid", prepay_id);
                wxPayMap.put("partnerid", config.getMchID());
                wxPayMap.put("package", "Sign=WXPay");
                String packageSign = WXPayUtil.generateSignature(wxPayMap, config.getKey());
                wxPayMap.put("sign", packageSign);
                result.putAll(wxPayMap);

            }

        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException("支付异常");
        }
        log.info("支付参数：" + JSON.toJSONString(result));
        return result;
    }

    public ApiResult<Object> transfers(HashMap<String, String> map) throws Exception {
        String accessId = map.get("accessId");//系统帐户
        String price = map.get("price");//金额 单位分
        String openId = map.get("openId"); //小程序支付携带openId
        String desc = map.get("desc");//提现描述
        String wasteNumber = map.get("wasteNumber");//提现流水号
        //获取system配置
        TSystem tSystem = new TSystem();
        tSystem.setAccessId(accessId);
        //或取system
        ApiResult<TSystem> system = systemServiceFeign.selectSystemByAccessId(tSystem);
        //获取系统配置信息
        ApiResult<TSystemConfig> systemConfig = systemServiceFeign.getSystemConfigByAccessId(tSystem);
        EntPayRequest entPayRequest = new EntPayRequest();
        entPayRequest.setAppid(system.getDataMap().getWxAppletsId());
        entPayRequest.setMchId(system.getDataMap().getWxMchId());
        entPayRequest.setPartnerTradeNo(wasteNumber);
        entPayRequest.setOpenid(openId);
        entPayRequest.setCheckName("NO_CHECK");
        entPayRequest.setAmount(Integer.parseInt(price));
        entPayRequest.setDescription(desc);
        entPayRequest.setSpbillCreateIp(getHostIp());
        EntPayResult entPayResult = null;
        try {
            //此处调用=============================================================
            // 通过Java配置来实例化Spring容器
            WxPayConfig wxPayConfig = new WxPayConfig();
            wxPayConfig.setAppId(system.getDataMap().getWxAppletsId());
            wxPayConfig.setMchId(system.getDataMap().getWxMchId());
            wxPayConfig.setMchKey(system.getDataMap().getWxMchSecret());
            wxPayConfig.setKeyPath(system.getDataMap().getCertificateUrl());
            WxPayService wxPayService = wxConfig.wxPayService(wxPayConfig);
            entPayResult = wxPayService.getEntPayService().entPay(entPayRequest);
            log.info("entPayResult : " + entPayResult);
            if(!entPayResult.getResultCode().equals("SUCCESS")){
//                if ( entPayResult.getErrCode().equals("SYSTEMERROR")){
//
//                }

                return ApiResult.newErrorException(ApiResultCode.SYS_ERROR);
            }
            System.out.println(entPayResult);
        } catch (WxPayException e) {
            log.error("付款失败，返回报文" + e);
            return ApiResult.newErrorException(ApiResultCode.SYS_ERROR);
        }
        return ApiResult.newSuccess();

    }

    public Object refund(HashMap<String, String> map) throws Exception {
        Map<String, String> data = new HashMap<>();
        String accessId = map.get("accessId");//系统帐户
        String outTradeNo = map.get("outTradeNo");//支付流水
        String outRefundNo = map.get("outRefundNo");//退款编号
        String totalFee = map.get("totalFee");//退款总金额
        String refundFee = map.get("refundFee");//退款金额
        //获取system配置
        TSystem tSystem = new TSystem();
        tSystem.setAccessId(accessId);
        ApiResult<TSystem> system = systemServiceFeign.selectSystemByAccessId(tSystem);

        data.put("out_refund_no", outRefundNo);
        data.put("out_trade_no", outTradeNo);
        data.put("total_fee", totalFee);
        data.put("refund_fee", refundFee);
        WXConfigUtil config = new WXConfigUtil();
        config.setMCH_ID("1483658602");
        config.setAPP_KEY("ca0be45f260bb3fae54c7992ab04ad58");
        config.setAPP_ID("wxc36339079c4df7a6");
        WXPay wxpay = new WXPay(config);
        data.put("appid", system.getDataMap().getWxAppletsId());
        data.put("mch_id", system.getDataMap().getWxMchId());
        data.put("nonce_str", WXPayUtil.generateNonceStr());
        data.put("sign", WXPayUtil.generateSignature(data, system.getDataMap().getWxMchSecret()));

        Map<String, String> resp = null;
        try {
//            String s = HttpClientUtil.doPost("https://api.mch.weixin.qq.com/secapi/pay/refund",data);
//            String s = wxpay.requestWithCert("https://api.mch.weixin.qq.com/secapi/pay/refund", wxpay.fillRequestData(data), 8000, 10000);
//            System.out.println(s);
            resp = wxpay.refund(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.err.println(resp);
        String return_code = resp.get("result_code");   //返回状态码
        String return_msg = resp.get("return_msg");     //返回信息

        String resultReturn = null;
        if ("SUCCESS".equals(return_code)) {
            String result_code = resp.get("result_code");       //业务结果
            String err_code_des = resp.get("err_code_des");     //错误代码描述
            if ("SUCCESS".equals(result_code)) {
                //表示退款申请接受成功，结果通过退款查询接口查询
                //修改用户订单状态为退款申请中（暂时未写）
                resultReturn = "退款申请成功";
            } else {
                log.info("订单号:{}错误信息:{}", err_code_des);
                resultReturn = err_code_des;
            }
        } else {
            log.info("订单号:{}错误信息:{}", return_msg);
            resultReturn = return_msg;
        }
        return return_code;

    }
}
